home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
Raven 1.2 Examples.sit
/
Raven 1.2 Examples
/
Quill
/
Source
/
PaneEditDialog.cpp
< prev
next >
Wrap
Text File
|
1997-08-26
|
14KB
|
590 lines
/*
* File: PaneEditDialog.cpp
* Function: A dialog box that knows how to edit panes.
* Written by: Jesse Jones
*
* Copyright ゥ 1996-1997 Jesse Jones.
* For conditions of distribution and use, see copyright notice in ZTypes.h
*
* Change History (most recent first):
*
* <2> 5/11/97 JDJ Uses GetNamedResource instead of Get1NamedResource.
* <1> 11/20/96 JDJ Created (from CPaneDialog)
*/
#include "PaneEditDialog.h"
#include <Resources.h>
#include <ZApplication.h>
#include <ZAttributes.h>
#include <ZDialogHandler.h>
#include <ZHierarchicalTableExtras.h>
#include <ZIntConversions.h>
#include <ZMiscUtils.h>
#include "ZPaneNode.h"
#include <ZScroller.h>
#include <ZSubNode.h>
#include <ZStringUtils.h>
#include <ZUndoableCommand.h>
#include <ZUndoMgr.h>
#include "BasePaneEditor.h"
#include "DialogBoxProxy.h"
#include "ViewContainer.h"
#include "WindowProxy.h"
//-----------------------------------
// Constants
//
const string kApplyMessage = "Apply";
//-----------------------------------
// Types
//
typedef THierarchicalIter<TPaneNode> CNodeIter;
// ===================================================================================
// class CUpdateResourceCommand
// ===================================================================================
class CUpdateResourceCommand : public TUndoableCommand {
typedef TUndoableCommand Inherited;
//-----------------------------------
// Initialization/Destruction
//
public:
virtual ~CUpdateResourceCommand();
CUpdateResourceCommand(TPane* pane);
//-----------------------------------
// New API
//
public:
CViewContainer* GetContainer();
//-----------------------------------
// Inherited API
//
public:
virtual string GetText() const;
protected:
virtual void OnDo();
virtual void OnUndo();
virtual void OnRedo();
//-----------------------------------
// Member data
//
protected:
TPane* mPane;
};
//---------------------------------------------------------------
//
// CUpdateResourceCommand::~CUpdateResourceCommand
//
//---------------------------------------------------------------
CUpdateResourceCommand::~CUpdateResourceCommand()
{
}
//---------------------------------------------------------------
//
// CUpdateResourceCommand::CUpdateResourceCommand
//
//---------------------------------------------------------------
CUpdateResourceCommand::CUpdateResourceCommand(TPane* pane)
{
ASSERT(pane != nil);
mPane = pane;
TWindow* window = dynamic_cast<TWindow*>(mPane->GetTopView());
if (window != nil)
mContext = window->GetUndoContext();
else
mContext = nil;
mDelete = mContext == nil;
}
//---------------------------------------------------------------
//
// CUpdateResourceCommand::GetContainer
//
//---------------------------------------------------------------
CViewContainer* CUpdateResourceCommand::GetContainer()
{
CViewContainer* container = nil;
TView* superView = mPane->GetSuperView();
if (superView == nil) {
if (TView* view = dynamic_cast<TView*>(mPane))
container = dynamic_cast<CViewContainer*>(view->FindSubPane("CViewContainer"));
} else {
container = dynamic_cast<CViewContainer*>(superView);
while (container == nil && superView != nil) {
superView = superView->GetSuperView();
container = dynamic_cast<CViewContainer*>(superView);
}
}
ASSERT(container != nil);
return container;
}
//---------------------------------------------------------------
//
// CUpdateResourceCommand::GetText
//
//---------------------------------------------------------------
string CUpdateResourceCommand::GetText() const
{
return ""; // should be inside a transaction
}
//---------------------------------------------------------------
//
// CUpdateResourceCommand::OnDo
//
//---------------------------------------------------------------
void CUpdateResourceCommand::OnDo()
{
this->GetContainer()->UpdateResource();
}
//---------------------------------------------------------------
//
// CUpdateResourceCommand::OnUndo
//
//---------------------------------------------------------------
void CUpdateResourceCommand::OnUndo()
{
this->GetContainer()->UpdateResource();
}
//---------------------------------------------------------------
//
// CUpdateResourceCommand::OnRedo
//
//---------------------------------------------------------------
void CUpdateResourceCommand::OnRedo()
{
this->GetContainer()->UpdateResource();
}
#pragma mark -
// ===================================================================================
// class CPaneEditDialog
// ===================================================================================
static TReanimatorRegister<CPaneEditDialog> sPaneEditDialogRegistrar;
//---------------------------------------------------------------
//
// CPaneEditDialog::~CPaneEditDialog
//
//---------------------------------------------------------------
CPaneEditDialog::~CPaneEditDialog()
{
}
//---------------------------------------------------------------
//
// CPaneEditDialog::CPaneEditDialog
//
//---------------------------------------------------------------
CPaneEditDialog::CPaneEditDialog()
{
mPane = nil;
mTable = nil;
mAttributes.eraseOnUpdate = false;
}
//---------------------------------------------------------------
//
// CPaneEditDialog::EditPane [static]
//
//---------------------------------------------------------------
void CPaneEditDialog::EditPane(TPane* pane)
{
CPaneEditDialog* dialog = CPaneEditDialog::Create(240, TApplication::Instance());
dialog->SetPane(pane);
string message = kNothingMessage;
{
TDialogHandler handler(dialog);
dialog->Show();
while (message != kCancelMessage && message != kOKMessage) {
message = handler.ProcessNextEvent();
if (message == kOKMessage) {
if (dialog->Validate())
dialog->Commit();
else
message = kNothingMessage;
} else if (message == kApplyMessage) {
if (dialog->Validate())
dialog->Apply();
else
message = kNothingMessage;
} else if (message == kCancelMessage)
dialog->Revert();
}
}
}
//---------------------------------------------------------------
//
// CPaneEditDialog::SetPane
//
//---------------------------------------------------------------
void CPaneEditDialog::SetPane(TPane* inPane)
{
ASSERT(inPane != nil);
if (dynamic_cast<CViewContainer*>(inPane) != nil)
inPane = inPane->GetSuperView();
mPane = inPane;
// Move the dialog to where the user last had it.
if (mPane->HasAttribute("Editor Frame")) {
TRectAttribute* attribute = dynamic_cast<TRectAttribute*>(mPane->GetAttribute("Editor Frame"));
this->SetLocation(attribute->GetValue()[topLeft]);
this->ForceOnScreen();
}
// Install the applicable editors.
this->CreateEditors();
// Tell the pane editors the pane they're working on.
CNodeIter iter(mTable);
while (iter) {
TPaneNode* node = *iter;
++iter;
TPane* pane = node->GetPane();
if (CRootPaneEditor* editor = dynamic_cast<CRootPaneEditor*>(pane))
editor->SetPane(mPane);
}
}
//---------------------------------------------------------------
//
// CPaneEditDialog::Validate
//
//---------------------------------------------------------------
bool CPaneEditDialog::Validate() const
{
bool valid = Inherited::Validate();
CNodeIter iter(mTable);
while (iter && valid) {
TPaneNode* node = *iter;
++iter;
TPane* pane = node->GetPane();
if (CRootPaneEditor* editor = dynamic_cast<CRootPaneEditor*>(pane))
valid = editor->Validate();
}
return valid;
}
//---------------------------------------------------------------
//
// CPaneEditDialog::Apply
//
//---------------------------------------------------------------
void CPaneEditDialog::Apply()
{
try {
CNodeIter iter(mTable);
while (iter) {
TPaneNode* node = *iter;
++iter;
TPane* pane = node->GetPane();
if (CRootPaneEditor* editor = dynamic_cast<CRootPaneEditor*>(pane))
editor->Apply();
}
} catch (const TBaseException& e) {
ReportError(LoadAppString("Couldn't apply the pane changes"), e);
} catch (...) {
ReportError(LoadAppString("Couldn't apply the pane changes"), LoadAppString("Unknown Error"));
}
}
//---------------------------------------------------------------
//
// CPaneEditDialog::Commit
//
//---------------------------------------------------------------
void CPaneEditDialog::Commit()
{
TWindow* window = dynamic_cast<TWindow*>(mPane->GetTopView());
if (window != nil) {
string text = LoadIndString(257, 2);
TMultipleUndoableCommand* command = new TMultipleUndoableCommand(window->GetUndoContext(), text);
try {
CNodeIter iter(mTable);
while (iter) {
TPaneNode* node = *iter;
++iter;
TPane* pane = node->GetPane();
if (CRootPaneEditor* editor = dynamic_cast<CRootPaneEditor*>(pane))
editor->Commit(command);
}
command->AddCommand(new CUpdateResourceCommand(mPane));
command->Post();
} catch (const TBaseException& e) {
delete command;
ReportError(LoadAppString("Couldn't change the pane"), e);
} catch (...) {
delete command;
ReportError(LoadAppString("Couldn't change the pane"), LoadAppString("Unknown Error"));
}
}
}
//---------------------------------------------------------------
//
// CPaneEditDialog::Revert
//
//---------------------------------------------------------------
void CPaneEditDialog::Revert()
{
try {
CNodeIter iter(mTable);
while (iter) {
TPaneNode* node = *iter;
++iter;
TPane* pane = node->GetPane();
if (CRootPaneEditor* editor = dynamic_cast<CRootPaneEditor*>(pane))
editor->Revert();
}
} catch (const TBaseException& e) {
ReportError(LoadAppString("Couldn't revert the pane changes"), e);
} catch (...) {
ReportError(LoadAppString("Couldn't revert the pane changes"), LoadAppString("Unknown Error"));
}
}
//---------------------------------------------------------------
//
// CPaneEditDialog::Create [static]
//
//---------------------------------------------------------------
CPaneEditDialog* CPaneEditDialog::Create(ResID id, MCommander* superCommander)
{
CPaneEditDialog* dialog = dynamic_cast<CPaneEditDialog*>(Inherited::Create(id, superCommander));
try {
if (dialog == nil)
throw TRuntimeException("CPaneEditDialog::Create created an object that wasn't the right type.");
} catch (...) {
delete dialog;
throw;
}
return dialog;
}
//---------------------------------------------------------------
//
// CPaneEditDialog::Create [static]
//
//---------------------------------------------------------------
MReanimatable* CPaneEditDialog::Create(MReanimatable* parent)
{
ASSERT(parent == nil);
if (CWindowProxy::msUseProxy)
return CDialogBoxProxy::Create(parent);
else
return new CPaneEditDialog;
}
//---------------------------------------------------------------
//
// CPaneEditDialog::OnReanimated
//
//---------------------------------------------------------------
void CPaneEditDialog::OnReanimated()
{
Inherited::OnReanimated();
TPushButton* control = dynamic_cast<TPushButton*>(this->FindSubPane("Apply"));
if (control != nil)
control->AddListener(this);
mTable = dynamic_cast<THierarchicalTable*>(this->FindSubPane("Table View"));
TScroller* scroller = dynamic_cast<TScroller*>(this->FindSubPane("Scroller")); // ・・ハshould do this from within Quill
if (scroller == nil)
throw TRuntimeException("we're hosed");
scroller->InstallView(mTable);
}
//---------------------------------------------------------------
//
// CPaneEditDialog::OnClose
//
//---------------------------------------------------------------
void CPaneEditDialog::OnClose()
{
if (mPane != nil) {
if (!mPane->HasAttribute("Editor Frame"))
mPane->AddAttribute("Editor Frame", new TRectAttribute);
TRectAttribute* attribute = dynamic_cast<TRectAttribute*>(mPane->GetAttribute("Editor Frame"));
attribute->SetValue(this->GetFrame());
}
Inherited::OnClose();
}
//---------------------------------------------------------------
//
// CPaneEditDialog::GetTable
//
//---------------------------------------------------------------
Handle CPaneEditDialog::GetTable()
{
Handle table = nil;
string className = typeid(*mPane).name();
table = GetNamedResource('EdId', StrToPStr(className));
if (table == nil) // should only happen when editing Quill's views
table = GetNamedResource('EdId', "¥pTPane");
ThrowIfResFail(table);
return table;
}
//---------------------------------------------------------------
//
// CPaneEditDialog::CreateEditors
//
//---------------------------------------------------------------
void CPaneEditDialog::CreateEditors()
{
#pragma options align=mac68k
struct SEditorTable {
short count;
unsigned char editStr[1];
};
#pragma options align=reset
SEditorTable** tableH = (SEditorTable**) this->GetTable();
HLock((Handle) tableH);
unsigned char* editStr = (**tableH).editStr;
for (short index = 0; index < (**tableH).count; index++) {
string str = PStrToStr(editStr);
string name = Parse(str, " ¥t");
TSubNode* parent = new TSubNode(mTable, mTable->GetRoot(), name, true);
mTable->GetRoot()->AppendNode(parent);
if (str[0] == '[') {
str = str.substr(1);
while (str.length() > 0) {
bool expand = true;
if (str[0] == '>') {
expand = false;
str = str.substr(1);
}
ResID id = StrToShort(Parse(str, " ¥t"));
// Panes that use the Control Manager need to be initialized with
// a valid port so we'll create the pane in the context it will
// be drawn in and then detach it (so we don't get hosed by
// origin adjustments when drawing the pane).
TPane* editor = TPane::Create(id, this);
this->RemoveSubPane(editor);
TSubNode* subNode = new TSubNode(mTable, parent, editor->GetName(), expand);
parent->AppendNode(subNode);
TPaneNode* leafNode = new TPaneNode(mTable, subNode, editor);
subNode->AppendNode(leafNode);
}
} else {
ResID id = StrToShort(Parse(str, " ¥t"));
TPane* editor = TPane::Create(id, this);
this->RemoveSubPane(editor);
TPaneNode* leafNode = new TPaneNode(mTable, parent, editor);
parent->AppendNode(leafNode);
}
editStr += *editStr + 1;
}
ReleaseResource((Handle) tableH);
}